package com.bocloud.cmp.server.config;

import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import com.bocloud.cmp.common.cache.DictionaryCache;
import com.bocloud.cmp.common.utils.IPTool;
import com.bocloud.cmp.dao.AlarmDao;
import com.bocloud.cmp.dao.CloudVendorDao;
import com.bocloud.cmp.dao.DictionaryDao;
import com.bocloud.cmp.driver.config.Configuration;
import com.bocloud.cmp.driver.config.ConfigurationCore;
import com.bocloud.cmp.entity.Dictionary;
import com.bocloud.cmp.entity.resource.CloudVendor;
import com.bocloud.cmp.server.utils.SnmpTrapReceiver;
import com.bocloud.cmp.service.utils.RegisterVendor;
import com.bocloud.common.enums.BoCloudConfig;
import com.bocloud.common.enums.BoCloudService;
import com.bocloud.common.model.Result;
import com.bocloud.common.utils.NicTools;
import com.bocloud.coordinator.config.client.SimpleZkClient;
import com.bocloud.coordinator.config.client.ZkClientHelper;
import com.bocloud.coordinator.esb.intf.EsbService;

@Component
public class Initialization {

	private static Logger logger = LoggerFactory.getLogger(Initialization.class);
	@Autowired
	private EsbService esbService;
	@Autowired
	private ZkClientHelper zkClientHelper;
	@Autowired
	private DictionaryDao dictionaryDao;
	@Value("${server.port:8080}")
	private String port;
	@Value("${server.ip:127.0.0.1}")
	private String ip;
	@Autowired
	private CloudVendorDao cloudVendorDao;

	@Value("${snmp.listen.url}")
	private String snmplistenAddress;

	@Autowired
	private AlarmDao alarmDao;

	public String getIp() {
		return ip;
	}

	public void setIp(String ip) {
		this.ip = ip;
	}

	/**
	 * @return the port
	 */
	public String getPort() {
		return port;
	}

	/**
	 * @param port
	 *            the port to set
	 */
	public void setPort(String port) {
		this.port = port;
	}

	/**
	 * 服务初始化
	 */
	@PostConstruct
	public void init() {
		this.register(); // 注册
		this.electLeader(); // 选主
		this.dictionary(); // 字典
		this.registerVendor();// 注册云供应商信息
		this.initConfig(); // 初始化配置
		new SnmpTrapReceiver(snmplistenAddress, alarmDao).run();
	}

	private void dictionary() {
		if (!DictionaryCache.isInit) {
			return;
		}
		logger.info("Start to init cache dictionary...");
		try {
			List<Dictionary> dictList = dictionaryDao.list();
			Map<String, String> itemMap = new ConcurrentHashMap<String, String>();
			for (Dictionary dict : dictList) {
				itemMap.put(dict.getValue(), dict.getName());
			}
			synchronized (DictionaryCache.class) {
				if (DictionaryCache.isInit) {
					DictionaryCache.writeCache(itemMap);
					DictionaryCache.isInit = false;
				}
			}
			logger.info("Cache dictionary successful!");
		} catch (Exception e) {
			logger.error("Cache dictionary exception!", e);
			System.exit(-1);
		}
	}

	private void registerVendor() {
		try {
			List<CloudVendor> list = cloudVendorDao.listAll();
			RegisterVendor.register(esbService, zkClientHelper, list);
		} catch (Exception e) {
			logger.error("register vendor failure:", e);
		}

	}

	/**
	 * 选主
	 */
	private void electLeader() {
		String path = BoCloudConfig.Leadership.getZkPath() + "/" + BoCloudService.Cmp.getZkNode();
		esbService.elect(path, null);
	}

	private void register() {
		String address = this.ip;
		if (!IPTool.isIp(address) || address.equalsIgnoreCase("127.0.0.1")) {
			address = NicTools.getIp();
		}
		if (StringUtils.hasText(address)) {
			String servicePath = address + ":" + port;
			Result result = esbService.register(BoCloudService.Cmp.getZkNode(), servicePath, null);
			logger.info(result.toString());
			if (!result.isSuccess()) {
				logger.error("服务启动失败！原因：[{}];[{}]", "服务注册失败！", result.getMessage());
				System.exit(-1);
			} else {
				logger.info("服务启动成功！");
				new Thread(new Runnable() {
					@Override
					public void run() {
						while (true) {
							try {
								Thread.sleep(1000 * 60);
								Result result = esbService.register(BoCloudService.Cmp.getZkNode(), servicePath, null);
								logger.info("Service Heartbeat Result : {}", result.isSuccess());
							} catch (InterruptedException e) {
								logger.error("Service Heartbeat Interruppted ");
							}
						}

					}
				}).start();
			}
			MDC.put("ip", ip);
			MDC.put("module", BoCloudService.Cmp.name());
		} else {
			logger.error("服务启动失败！原因：[{}]", "获取主机IP失败！");
			System.exit(-1);
		}
	}

	private void initConfig() {
		String path = BoCloudConfig.Butler.getZkPath();
		SimpleZkClient client = new SimpleZkClient(this.zkClientHelper.getClient());
		// 判断是否基础路径是否存在，不存在则创建
		if (!client.isExists(path, false)) {
			client.create(path, "");
		}
		Configuration config = Configuration.instance();
		ConfigurationCore core = new ConfigurationCore(path, client, config);
		config.update(core.getData());
	}

	@PreDestroy
	public void destory() {
		logger.info("Service Stopped");
	}

}
